package com.bing.habit.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SimplePropertyPreFilter;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 日志切面类
 */
@Aspect
@Component
@Order(1)
@Slf4j
public class LogAspectConfig {

    //@Pointcut("execution(* com.bing.habit.controller..*.*(..))")
    //只记录增删改 日志
    @Pointcut("execution(* com.bing.habit.controller..*.add*(..)) " +
            "|| execution(* com.bing.habit.controller..*.del*(..)) " +
            "|| execution(* com.bing.habit.controller..*.update*(..))"+
            "|| execution(* com.bing.habit.controller..*.upload*(..))" )
    private void webLog() {
    }

    @Before(value = "webLog()")
    public void before(JoinPoint joinPoint) {
        ServletRequestAttributes requestAttributes =
                (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = requestAttributes.getRequest();
//        log.info("======================请求日志的打印[入参]=======================");
//        log.info("请求地址:{}", Optional.of(request.getRequestURI().toString()).orElse(null));
//        log.info("请求方式:{}", request.getMethod());
//        log.info("请求类方法参数:{}", JSONObject.toJSONString(JSONObject.toJSONString(filterArgs(joinPoint.getArgs()))));
//        log.info("======================请求日志的打印[入参结束]====================");
        //简化格式
        log.info("入参日志"+ "["+ Thread.currentThread().getId() +"]"+
                        " url={}, method={}, ip={}, args={}"
                , request.getRequestURI(),request.getMethod(),request.getRemoteAddr(),joinPoint.getArgs());
    }

    @Around("webLog()")
    public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        Object result = proceedingJoinPoint.proceed();

        // 当某些字段太敏感，或者是太长时，就不显示
        String[] excludeProperties = {"password", "file"};
        SimplePropertyPreFilter filters = new SimplePropertyPreFilter();
        for (String str : excludeProperties) {
            filters.getExcludes().add(str);
        }
//        log.info("======================请求日志的打印[出参]=======================");
//        log.info("返回的结果: {}", JSON.toJSONString(result, filters));
//        log.info("=== 结束时，总耗时：{} ms ===", System.currentTimeMillis() - startTime);
//        log.info("======================请求日志的打印[出参结束]====================");
        //简化版本
        long time = System.currentTimeMillis() - startTime;
        log.info("出参日志" +"["+ Thread.currentThread().getId() +"]" + " 耗时: " +  time + " ms" +
                " 返回的结果: {}",JSON.toJSONString(result, filters));
        return result;
    }

    private List<Object> filterArgs(Object[] objects) {
        return Arrays.stream(objects).filter(obj -> !(obj instanceof MultipartFile)
                && !(obj instanceof HttpServletResponse)
                && !(obj instanceof HttpServletRequest)).collect(Collectors.toList());
    }
}
